package com.shuai.frame.server;

import com.shuai.frame.model.RpcRequest;
import com.shuai.frame.model.RpcResponse;
import com.shuai.frame.registry.LocalRegister;
import com.shuai.frame.serializer.JdkSerializer;
import com.shuai.frame.serializer.Serializer;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;

import java.io.IOException;
import java.lang.reflect.Method;

public class HttpServerHandler implements Handler<HttpServerRequest> {
    private static final Serializer serializer = new JdkSerializer();

    /**
     * 1. 反序列化请求对象为RpcRequest
     * 2. 根据反射调用服务方法
     * 3. 根据服务响应封装和序列化RpcResponse返回
     */
    @Override
    public void handle(HttpServerRequest request) {
        System.out.printf("接收到请求：请求方法-{%s}，请求uri-{%s}", request.method(), request.uri());
        request.bodyHandler(buffer -> {
            HttpServerResponse response = request.response();
            RpcResponse rpcResponse = new RpcResponse();// 反序列化请求对象
            try {
                RpcRequest rpcRequest = serializer.deserialize(buffer.getBytes(), RpcRequest.class);
                if (rpcRequest == null) {
                    rpcResponse.setMessage("无法解析请求参数");
                    doResponse(response, rpcResponse);
                    return;
                }
                Class<?> serviceImpl = LocalRegister.getService(rpcRequest.getServiceName());
                // 通过反射创建服务对象
                Object serviceInstance = serviceImpl.newInstance();
                Method invokeMethod = serviceImpl.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
                Object serviceResponse = invokeMethod.invoke(serviceInstance, rpcRequest.getArgs());
                rpcResponse.setData(serviceResponse);
                rpcResponse.setDataType(invokeMethod.getReturnType());
                rpcResponse.setMessage("处理成功");
            } catch (Exception e) {
                e.printStackTrace();
                rpcResponse.setException(e);
                rpcResponse.setMessage("服务处理异常");
                doResponse(response, rpcResponse);
            }
            doResponse(response, rpcResponse);
        });
    }

    private void doResponse(HttpServerResponse response, RpcResponse rpcResponse) {
        byte[] bufferResponse = new byte[0];
        try {
            bufferResponse = serializer.serialize(rpcResponse);
        } catch (IOException e) {
            e.printStackTrace();
        }
        response.putHeader("content-type", "application/json;charset=utf8");
        response.end(Buffer.buffer(bufferResponse));
    }
}
